package com.yootk.producer.config;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.rabbit.batch.BatchingStrategy;
import org.springframework.amqp.rabbit.batch.SimpleBatchingStrategy;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.PooledChannelConnectionFactory;
import org.springframework.amqp.rabbit.core.BatchingRabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
@PropertySource("classpath:config/amqp.properties")

public class RabbitMQConfig {
    @Value("${amqp.rabbitmq.host}")
    private String host;
    @Value("${amqp.rabbitmq.port}")
    private Integer port;
    @Value("${amqp.rabbitmq.username}")
    private String username;
    @Value("${amqp.rabbitmq.password}")
    private String password;
    @Value("${amqp.rabbitmq.vhost}")
    private String vhost;
    @Value("${amqp.rabbitmq.routing.key}")
    private String routingKey;
    @Value("${amqp.rabbitmq.exchange.name}")
    private String exchangeName;
    @Bean
    public com.rabbitmq.client.ConnectionFactory amqpConnectionFactory() { // 连接工厂类
        com.rabbitmq.client.ConnectionFactory factory =
                new com.rabbitmq.client.ConnectionFactory();
        factory.setHost(this.host);
        factory.setPort(this.port);
        factory.setUsername(this.username);
        factory.setPassword(this.password);
        factory.setVirtualHost(this.vhost);
        return factory;
    }
    @Bean
    public TaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler() ;
        scheduler.setPoolSize(16);
        return scheduler ;
    }

    @Bean
    public org.springframework.amqp.rabbit.connection.ConnectionFactory
    springConnectionFactory(
            com.rabbitmq.client.ConnectionFactory amqpConnectionFactory) {
        org.springframework.amqp.rabbit.connection.ConnectionFactory factory; // Spring连接工厂
        factory = new PooledChannelConnectionFactory(
                amqpConnectionFactory);
        return factory;
    }
    @Bean
    public RetryTemplate template(){
        RetryTemplate template = new RetryTemplate() ;
        ExponentialBackOffPolicy policy = new ExponentialBackOffPolicy() ;
        policy.setInitialInterval(500);
        policy.setMaxInterval(10000);
        policy.setMultiplier(10.0);
        template.setBackOffPolicy(policy);
        return template ;
    }
    @Bean
    public Exchange exchange(){
        return new FanoutExchange(this.exchangeName) ;
    }
    @Bean
    public AmqpTemplate amqpTemplate(
            RetryTemplate template,
            ConnectionFactory factory,
            TaskScheduler taskScheduler){
        int batchSize = 20 ;
        int bufferLimit = 4096 ;
        int timeout = 10000 ;
        BatchingStrategy strategy = new SimpleBatchingStrategy(batchSize,bufferLimit,timeout) ;
        BatchingRabbitTemplate template1 = new BatchingRabbitTemplate(factory,strategy,taskScheduler) ;
        template1.setRetryTemplate(template);
        template1.setExchange(this.exchangeName);
        return template1 ;
    }
}
